package com.sjr.easy.chat.app.controller;

import com.alibaba.fastjson2.JSON;
import com.sjr.easy.chat.app.dto.AppTokenInfo;
import com.sjr.easy.chat.app.utils.AppTokenManager;
import com.sjr.easy.chat.app.utils.SequenceUtils;
import com.sjr.easy.chat.business.ConversationBusiness;
import com.sjr.easy.chat.dto.Result;
import com.sjr.easy.chat.model.*;
import com.sjr.easy.chat.service.ChatGroupService;
import com.sjr.easy.chat.service.ChatGroupUserService;
import com.sjr.easy.chat.service.ContactService;
import com.sjr.easy.chat.service.UserService;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.ListUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@RestController
public class AppChatGroupController {

    @Autowired
    private ChatGroupService chatGroupService;

    @Autowired
    private ChatGroupUserService chatGroupUserService;

    @Autowired
    private UserService userService;

    @Autowired
    private ContactService contactService;

    @Autowired
    private AppTokenManager appTokenManager;

    @Autowired
    private SequenceUtils sequenceUtils;

    @Autowired
    private ConversationBusiness conversationBusiness;

    @Data
    static class CreateChatGroupReqParams {
        @ApiModelProperty("聊天群名称")
        private String chatGroupName;
        @ApiModelProperty("好友用户ID集合")
        private Set<Long> friendUserIdSet;
    }

    @ApiOperation("创建聊天群")
    @PostMapping("/app/chatGroup/createChatGroup")
    public Result<Conversation> createChatGroup(@RequestBody CreateChatGroupReqParams req) {

        AppTokenInfo tokenInfo = appTokenManager.getTokenInfo();

        if (CollectionUtils.isEmpty(req.friendUserIdSet)) {
            log.error("群用户列表为空");
            return Result.error("群用户列表为空");
        }
        Map<Long, Contact> contactsMap = ListUtils
                .emptyIfNull(contactService.selectContactsListByUserId(tokenInfo.getId()))
                .stream()
                .collect(Collectors.toMap(Contact::getContactUserId, Function.identity()));

        for (Long friendUserId : req.friendUserIdSet) {
            if (!contactsMap.containsKey(friendUserId)) {
                log.error("只允许邀请好友加入群聊:{}", friendUserId);
                return Result.error("只允许邀请好友加入群聊");
            }
        }

        Long chatGroupCode = sequenceUtils.genChatGroupCode();
        ChatGroup chatGroup = chatGroupService.createChatGroup(
                req.chatGroupName, chatGroupCode, tokenInfo.getId(), req.friendUserIdSet);

        Conversation conversation = conversationBusiness.getOrCreateConversation(
                2, tokenInfo.getId(), null, chatGroup.getId());
        return Result.success(conversation);
    }

    @Data
    static class GetUserChatGroupInfoListResultData {

        @ApiModelProperty("")
        private Long id;

        @ApiModelProperty("群编号")
        private Long code;

        @ApiModelProperty("管理员用户ID")
        private Long managerUserId;

        @ApiModelProperty("创建时间")
        private Date createTime;

        @ApiModelProperty("群名称")
        private String name;

        private List<GetUserChatGroupInfoListResultData.ChatGroupUserItem> chatGroupUserItemList;

        @Data
        static class ChatGroupUserItem {
            @ApiModelProperty("")
            private Long id;

            @ApiModelProperty("用户编号")
            private String code;

            @ApiModelProperty("昵称")
            private String nickname;

            @ApiModelProperty("手机号")
            private String phone;

            @ApiModelProperty("用户头像")
            private String headPortrait;

            @ApiModelProperty("用户头像存储类型：http存储类型可以直接加载、local类型需要通过指定接口加载图片")
            private String headPortraitStoreType;
        }
    }

    @ApiOperation("查询用户加入的所有聊天群信息")
    @GetMapping("/app/chatGroup/getUserChatGroupInfoList")
    public Result<List<GetUserChatGroupInfoListResultData>> getUserChatGroupInfoList() {
        AppTokenInfo tokenInfo = appTokenManager.getTokenInfo();
        log.info("userId:{}", tokenInfo.getId());
        List<Long> chatGroupIdList = ListUtils
                .emptyIfNull(chatGroupUserService.selectByUserId(tokenInfo.getId()))
                .stream()
                .map(ChatGroupUser::getChatGroupId).toList();
        List<ChatGroup> chatGroupList = ListUtils.emptyIfNull(chatGroupService.getChatGroupByIdList(chatGroupIdList));

        List<ChatGroupUser> chatGroupUserList = ListUtils
                .emptyIfNull(chatGroupUserService.selectByChatGroupIdList(chatGroupIdList));

        // 按chatGroupId分组的群聊成员map
        Map<Long, List<ChatGroupUser>> groupedChatGroupUser = chatGroupUserList
                .stream()
                .collect(Collectors.groupingBy(ChatGroupUser::getChatGroupId));
        List<Long> userIdList = chatGroupUserList.stream().map(ChatGroupUser::getUserId).toList();

        // 用户Map
        Map<Long, User> userMap = ListUtils.emptyIfNull(userService.selectByIdList(userIdList))
                .stream()
                .collect(Collectors.toMap(User::getId, Function.identity()));

        List<GetUserChatGroupInfoListResultData> getUserChatGroupInfoListItemList = new ArrayList<>();
        for (ChatGroup chatGroup : chatGroupList) {
            GetUserChatGroupInfoListResultData item = new GetUserChatGroupInfoListResultData();
            BeanUtils.copyProperties(chatGroup, item);

            List<GetUserChatGroupInfoListResultData.ChatGroupUserItem> chatGroupUserItemList = ListUtils
                    .emptyIfNull(groupedChatGroupUser.get(chatGroup.getId()))
                    .stream().map(chatGroupUser -> {
                        GetUserChatGroupInfoListResultData.ChatGroupUserItem chatGroupUserItem =
                                new GetUserChatGroupInfoListResultData.ChatGroupUserItem();
                        User user = userMap.get(chatGroupUser.getUserId());
                        if (user != null) {
                            BeanUtils.copyProperties(user, chatGroupUserItem);
                        } else {
                            log.error("用户信息查询失败:{}", JSON.toJSONString(chatGroupUser));
                        }
                        return chatGroupUserItem;
                    }).filter(chatGroupUserItem -> {
                        if (chatGroupUserItem.code == null) {
                            log.error("chatGroupUserItem:{}", JSON.toJSONString(chatGroupUserItem));
                            return false;
                        }
                        return true;
                    })
                    .toList();
            item.setChatGroupUserItemList(chatGroupUserItemList);

            getUserChatGroupInfoListItemList.add(item);
        }
        return Result.success(getUserChatGroupInfoListItemList);
    }


    @Data
    static class GetChatGroupDetailResultData {

        @ApiModelProperty("")
        private Long id;

        @ApiModelProperty("群编号")
        private Long code;

        @ApiModelProperty("管理员用户ID")
        private Long managerUserId;

        @ApiModelProperty("创建时间")
        private Date createTime;

        @ApiModelProperty("群名称")
        private String name;

        private List<ChatGroupUserItem> chatGroupUserItemList;

        @Data
        static class ChatGroupUserItem {
            @ApiModelProperty("")
            private Long id;

            @ApiModelProperty("用户编号")
            private String code;

            @ApiModelProperty("昵称")
            private String nickname;

            @ApiModelProperty("手机号")
            private String phone;

            @ApiModelProperty("用户头像")
            private String headPortrait;

            @ApiModelProperty("用户头像存储类型：http存储类型可以直接加载、local类型需要通过指定接口加载图片")
            private String headPortraitStoreType;
        }
    }

    @ApiOperation("查询聊天群信息")
    @GetMapping("/app/chatGroup/getChatGroupDetail")
    public Result<GetChatGroupDetailResultData> getChatGroupDetail(@RequestParam("chatGroupId") Long chatGroupId) {
        log.info("chatGroupId:{}", chatGroupId);
        AppTokenInfo tokenInfo = appTokenManager.getTokenInfo();
        ChatGroupUser chatGroupUser = chatGroupUserService.selectByUserIdAndChatGroupId(tokenInfo.getId(), chatGroupId);
        if (chatGroupUser == null) {
            log.info("无法查询未加入的聊天群信息");
            return Result.error("无法查询未加入的聊天群信息");
        }
        GetChatGroupDetailResultData resultData = new GetChatGroupDetailResultData();

        ChatGroup chatGroup = chatGroupService.selectById(chatGroupId);
        BeanUtils.copyProperties(chatGroup, resultData);

        List<ChatGroupUser> chatGroupUserList = ListUtils.emptyIfNull(chatGroupUserService.selectByChatGroupId(chatGroupId));
        List<Long> userIdList = chatGroupUserList.stream().map(ChatGroupUser::getUserId).collect(Collectors.toList());
        Map<Long, User> userMap = ListUtils.emptyIfNull(userService.selectByIdList(userIdList))
                .stream()
                .collect(Collectors.toMap(User::getId, Function.identity()));

        resultData.chatGroupUserItemList = chatGroupUserList.stream().map(item -> {
            GetChatGroupDetailResultData.ChatGroupUserItem chatGroupUserItem = new GetChatGroupDetailResultData.ChatGroupUserItem();
            Long userId = item.getUserId();
            User user = userMap.get(userId);
            BeanUtils.copyProperties(user, chatGroupUserItem);
            return chatGroupUserItem;
        }).toList();
        log.debug("resp:{}", resultData);
        return Result.success(resultData);
    }

    @Data
    static class QuitChatGroupReqParams {
        Long chatGroupId;
    }

    @ApiOperation("退出群聊")
    @PostMapping("/app/chatGroup/quitChatGroup")
    public Result<Object> quitChatGroup(@RequestBody QuitChatGroupReqParams reqParams) {
        log.info("reqParams:{}", JSON.toJSONString(reqParams));
        AppTokenInfo tokenInfo = appTokenManager.getTokenInfo();
        Objects.requireNonNull(reqParams.getChatGroupId(), "chatGroupId不允许为空");
        chatGroupUserService.quitChatGroup(reqParams.getChatGroupId(), tokenInfo.getId());
        return Result.success();
    }
}
